/*******************************************************************************
 * Copyright (c) 2008-2009 zhang yuexiang.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */ 
package org.xfeep.asura.bootstrap.test;


import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;

import org.junit.After;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.xfeep.asura.bootstrap.Asura;
import org.xfeep.asura.bootstrap.MemoryComponentLoader;
import org.xfeep.asura.bootstrap.ResetableExcutorServiceUtil;
import org.xfeep.asura.core.Component;
import org.xfeep.asura.core.ComponentInstance;
import org.xfeep.asura.core.Reference;
import org.xfeep.asura.core.ServiceSpace;
import org.xfeep.asura.core.annotation.Activate;
import org.xfeep.asura.core.annotation.Ref;
import org.xfeep.asura.core.annotation.Service;
import org.xfeep.asura.core.console.CommandLineService;
import org.xfeep.asura.core.util.InlineExecutorService;

public class AsuraBootPerformanceTestSet {

	static long start;
	static String type;
	CountDownLatch countDownLatch;
	static int max = 10000;
	static ServiceSpace serviceSpace;
	static int count = 0;
	
	@Service
	public static class DepAllCoreComponent {
		
//		static CountDownLatch countDownLatch;
		
		@Ref
		org.xfeep.asura.core.config.ConfigAdminService c;
		
		@Ref
		org.xfeep.asura.core.ComponentFactoryService cfs;
		
//		@Ref
//		org.xfeep.asura.core.console.CommandLineService cls;
		
		@Ref
		org.xfeep.asura.core.logger.TinyLogService tls;
		
		@Ref
		org.xfeep.asura.core.SimpleRegisterService srs;
		
		@Activate
		public void activate() {
//			countDownLatch.countDown();
			if (++count == max){
				System.out.println(type  + "  " + max + " cost :" + (System.currentTimeMillis() - start));
			}
		}
		
	}
	
	@BeforeClass
	public static void preLoader() throws Exception {
		MemoryComponentLoader m = new MemoryComponentLoader();
		Class<?> c = DepAllCoreComponent.class;
		m.getStaticLoadComponents(AsuraBootPerformanceTestSet.class.getClassLoader());
//		Runnable cmd = new Runnable(){
//			public void run() {
//				BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
//				String cmd = null;
//				try {
//					while ( (cmd = reader.readLine()) != null ){
//						if ("ss".equalsIgnoreCase(cmd)){
//							printServices(serviceSpace, System.out, 0);
//						}
//					}
//				} catch (Throwable e) {
//					e.printStackTrace();
//				}
//			}
//		};
//		new Thread(cmd).start();
	}
	
	@Before
	public void setUp() throws Exception {
	}

	@Test
	public void testSingleThreadMemoryModel() throws Exception {
		count = 0;
		type = "SingleThreadMemoryModel";
		Asura a = new Asura(this.getClass().getClassLoader(), new InlineExecutorService());
		a.addComponentIngorePattern(CommandLineService.class.getName());
		start = System.currentTimeMillis();
		for (int i = 0; i < max; i++){
//			countDownLatch = new CountDownLatch(1);
//			DepAllCoreComponent.countDownLatch = countDownLatch;
			a.start(new MemoryComponentLoader(), new MemoryComponentLoader(DepAllCoreComponent.class));
//			countDownLatch.await();
			a.shutdown();
		}
		System.out.println(type  + "  " + max + " cost :" + (System.currentTimeMillis() - start));
	}
	

	@Test
	public void testTwoThreadMemoryModel() throws Exception {
		type = "TwoThreadMemoryModel";
		Asura a = new Asura(this.getClass().getClassLoader(), ResetableExcutorServiceUtil.getExecutorService(2));
		a.addComponentIngorePattern(CommandLineService.class.getName());
		start = System.currentTimeMillis();
		for (int i = 0; i < max; i++){
//			a.setExecutorService(Executors.newFixedThreadPool(2));
//			countDownLatch = new CountDownLatch(1);
//			DepAllCoreComponent.countDownLatch = countDownLatch;
			a.start(new MemoryComponentLoader(), new MemoryComponentLoader(DepAllCoreComponent.class));
//			serviceSpace = a.getComponentManager().getApplicationServiceSpace();
//			ResetableExcutorServiceUtil.serviceEventCenter = serviceSpace.getEventCenter();
//			countDownLatch.await();
//			ResetableExcutorServiceUtil.waitAllfinish(1);
//			ResetableExcutorServiceUtil.waitAllfinish(0);
			a.shutdown();
		}
		System.out.println(type  + "  " + max + " cost :" + (System.currentTimeMillis() - start));
	}
	
	
	@After
	public void tearDown() throws Exception {
	}
	
	public static void printServices(ServiceSpace space, PrintStream out, int level){
		out.println("ServiceSpace[id="+space.getId()+"], level="+level);
		for (Component c : space.getAllComponent()){
			out.print("\tcomponent["+c.getDefinition().getImplement().getName()+"{");
			for (Class<?> s : c.getDefinition().getInterfaces()){
				out.print(s.getName());
				out.print(",");
			}
			List<ComponentInstance> cis = c.getInstances(null);
			out.println("}, status=" + c.getStatus()+", registered " + cis.size()+"]");
			for (Reference r : c.getReferences()){
				out.println("\t\tref[id="+ r.getDefinition().getName() + ", service="
						+r.getServiceClass().getName() +", matcher=" + r.getDetailMatcher()
						+", isSatisfied=" + r.isSatisfied()
						+"]");
			}
			for (ComponentInstance ci : cis){
				out.println("\t\tservice["+ci.getCurrentService()+"], config="+ci.getProperties());
			}
		}
		if (space.getChildren() != null){
			for (ServiceSpace cs : space.getChildren().values()){
				printServices(cs, out, level+1);
			}
		}
	}

}
